package com.furongji.education.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.furongji.common.domain.vo.CourseViewCountVo;
import com.furongji.common.domain.vo.SectionVo;
import com.furongji.common.domain.vo.VideoPlayPageVo;
import com.furongji.common.enums.CourseEnum;
import com.furongji.common.exception.MyException;
import com.furongji.common.result.Result;
import com.furongji.education.clients.OrderFeignClient;
import com.furongji.education.clients.VodFeignClient;
import com.furongji.education.domain.dto.CourseDto;
import com.furongji.education.domain.po.*;
import com.furongji.common.domain.query.CourseQuery;
import com.furongji.education.domain.query.CourseFrontQuery;
import com.furongji.education.domain.vo.ChapterVo;
import com.furongji.education.domain.vo.CourseFrontVo;
import com.furongji.education.domain.vo.CoursePublishVo;
import com.furongji.education.mapper.ChapterMapper;
import com.furongji.education.mapper.CourseMapper;
import com.furongji.education.mapper.SectionMapper;
import com.furongji.education.mapper.TeacherMapper;
import com.furongji.education.service.ChapterService;
import com.furongji.education.service.CourseService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.furongji.education.service.CourseViewLogService;
import com.furongji.education.service.SubjectService;
import lombok.RequiredArgsConstructor;
import org.springframework.beans.BeanUtils;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;

import java.math.BigDecimal;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 课程 服务实现类
 * </p>
 *
 * @author furongji
 * @since 2025-05-19
 */
@Service
@RequiredArgsConstructor
public class CourseServiceImpl extends ServiceImpl<CourseMapper, Course> implements CourseService {

    private final SubjectService subjectService;

    private final ChapterMapper chapterMapper;

    private final ChapterService chapterService;

    private final SectionMapper sectionMapper;

    private final VodFeignClient vodFeignClient;

    private final OrderFeignClient orderFeignClient;

    private final RedisTemplate<String, Object> redisTemplate;

    private final TeacherMapper teacherMapper;

    private final CourseMapper courseMapper;

    private final CourseViewLogService courseViewLogService;

    @Override
    public String saveCourse(CourseDto courseDto) {
        // 创建课程对象，对象拷贝
        Course course = new Course();
        BeanUtils.copyProperties(courseDto, course);
        // 设置课程状态为已发布
        course.setStatus(CourseEnum.Draft);
        // 根据课程id查询课程分类表获取父id
        String subjectId = course.getSubjectId();
        LambdaQueryWrapper<Subject> subjectWrapper = new LambdaQueryWrapper<>();
        subjectWrapper.eq(Subject::getId, subjectId);
        Subject subject = subjectService.getOne(subjectWrapper);
        // 设置课程的父id
        course.setSubjectParentId(subject.getParentId());
        boolean flag = super.save(course);
        if (!flag) {
            throw new MyException(20001, "课程存储失败");
        }
        return course.getId();
    }

    @Override
    public CoursePublishVo getPublishCourseInfo(String id) {
        return this.baseMapper.getPublishCourseInfo(id);
    }

    @Override
    public IPage<Course> pageCourseQuery(IPage<Course> page, CourseQuery courseQuery) {
        if (courseQuery != null) {
            String title = courseQuery.getTitle();
            String subjectId = courseQuery.getSubjectId();
            String subjectParentId = courseQuery.getSubjectParentId();
            String teacherId = courseQuery.getTeacherId();
            LambdaQueryWrapper<Course> courseWrapper = new LambdaQueryWrapper<>();
            if (StringUtils.hasText(title)) {
                courseWrapper.like(Course::getTitle, title);
            }
            if (StringUtils.hasText(subjectId)) {
                courseWrapper.eq(Course::getSubjectId, subjectId);
            }
            if (StringUtils.hasText(subjectParentId)) {
                courseWrapper.eq(Course::getSubjectParentId, subjectParentId);
            }
            if (StringUtils.hasText(teacherId)) {
                courseWrapper.eq(Course::getTeacherId, teacherId);
            }
            courseWrapper.orderByDesc(Course::getGmtCreate);
            return super.page(page, courseWrapper);
        } else {
            return super.page(page);
        }
    }

    // TODO 后续改用RabbitMQ
    @Override
    @Transactional
    public void deleteCourseById(String id) {
        LambdaQueryWrapper<Section> sectionWrapper = new LambdaQueryWrapper<>();
        sectionWrapper.eq(Section::getCourseId, id);
        List<Section> sectionList = sectionMapper.selectList(sectionWrapper);
        List<String> videoIdList = sectionList.stream().map(Section::getVideoSourceId).collect(Collectors.toList());
//        if (videoIdList.size() < 1 && videoIdList.isEmpty()) {
//            throw new MyException(20001, "视频Id不能为空");
//        }

        System.err.println("edu-service:" + videoIdList);

        // 远程调用
        vodFeignClient.removeVideoList(videoIdList);

        sectionMapper.deleteSection(id);
        chapterMapper.deleteChapter(id);
        this.baseMapper.deleteById(id);
    }

    // 根据讲师id获取对应的课程
    @Override
    public List<Course> getApiCourseInfoByTeacherId(String teacherId) {
        LambdaQueryWrapper<Course> courseWrapper = new LambdaQueryWrapper<>();
        courseWrapper.eq(Course::getTeacherId, teacherId);
        List<Course> courseList = super.list(courseWrapper);
        return courseList;
    }

    @Override
    public IPage<Course> getApiCourseList(IPage<Course> page, CourseFrontQuery courseFrontQuery) {

        String buyCountSort = courseFrontQuery.getBuyCount();
        String viewCountSort = courseFrontQuery.getViewCount();
        String priceSort = courseFrontQuery.getPrice();
        String gmtCreateSort = courseFrontQuery.getGmtCreate();
        String subjectParentId = courseFrontQuery.getSubjectParentId();
        String subjectId = courseFrontQuery.getSubjectId();

        LambdaQueryWrapper<Course> courseWrapper = new LambdaQueryWrapper<>();
        // 1为降序，2为升序
        if (StringUtils.hasText(buyCountSort)) {
            if (buyCountSort.equals("1")) {
                courseWrapper.orderByDesc(Course::getBuyCount);
            } else if (buyCountSort.equals("2")) {
                courseWrapper.orderByAsc(Course::getBuyCount);
            }
        }

        if (StringUtils.hasText(viewCountSort)) {
            if (viewCountSort.equals("1")) {
                courseWrapper.orderByDesc(Course::getViewCount);
            } else if (viewCountSort.equals("2")) {
                courseWrapper.orderByAsc(Course::getViewCount);
            }
        }

        if (StringUtils.hasText(priceSort)) {
            if (priceSort.equals("1")) {
                courseWrapper.orderByDesc(Course::getPrice);
            } else if (priceSort.equals("2")) {
                courseWrapper.orderByAsc(Course::getPrice);
            }
        }

        if (StringUtils.hasText(gmtCreateSort)) {
            if (gmtCreateSort.equals("1")) {
                courseWrapper.orderByDesc(Course::getGmtCreate);
            } else if (gmtCreateSort.equals("2")) {
                courseWrapper.orderByAsc(Course::getGmtCreate);
            }
        }

        if (StringUtils.hasText(subjectParentId)) {
            courseWrapper.eq(Course::getSubjectParentId, subjectParentId);
        }
        if (StringUtils.hasText(subjectId)) {
            courseWrapper.eq(Course::getSubjectId, subjectId);
        }

        IPage<Course> result = super.page(page, courseWrapper);
        return result;
    }


    // TODO 获取课程详细信息,后续从本地线程池中取userId
    @Override
    public CourseFrontVo getApiCourseInfo(String courseId, String userId) {
        CourseFrontVo courseFrontVo = baseMapper.getFrontCourseInfo(courseId);
        if (courseFrontVo == null) {
            throw new MyException(20001, "课程不存在，ID：" + courseId);
        }
        List<ChapterVo> chapterAndSection = chapterService.getChapterAndSection(courseId);
        courseFrontVo.setChapterVoList(chapterAndSection);
        if (StringUtils.hasText(userId)) {
            Integer code = orderFeignClient.isPurchaseCourse(userId, courseId).getCode();
            if (code == 20000) {
                courseFrontVo.setPurchase(true);
            }
        }
        String key = "course:view:" + userId + ":" + courseId;
        Boolean isView = redisTemplate.hasKey(key);
        if (Boolean.FALSE.equals(isView)) {
            courseMapper.update(null, new LambdaUpdateWrapper<Course>()
                    .eq(Course::getId, courseId)
                    .setSql("view_count = view_count + 1"));
            redisTemplate.opsForValue().set(key, true, 30, TimeUnit.MINUTES);
            CourseViewLog courseViewLog = new CourseViewLog();
            courseViewLog.setCourseId(courseId);
            courseViewLog.setCourseTitle(courseFrontVo.getTitle());
            courseViewLog.setUserId(userId);
            courseViewLogService.save(courseViewLog);
        }
        return courseFrontVo;
    }

    // 获取用户端首页课程列表
    public Object getIndexCourseList(Integer current, Integer size, CourseQuery courseQuery) {
        String cacheKey = "courseCache" + current + size;

        Object cacheData = redisTemplate.opsForValue().get(cacheKey);

        if (cacheData != null) {
            System.err.println("redis: " + cacheData);
            return cacheData;
        }

//        IPage<Course> page = new Page<>(current, size);
//        super.page(page, new CourseQuery()).getData();
        IPage<Course> page = new Page<>(current, size);
        IPage<Course> courseData = pageCourseQuery(page, new CourseQuery());
        redisTemplate.opsForValue().set(cacheKey, courseData, 10, TimeUnit.MINUTES);
        return courseData;
    }

    @Override
    public VideoPlayPageVo getCourseInfoWithSections(String videoId) {
        VideoPlayPageVo videoPlayPageVo = new VideoPlayPageVo();

        LambdaQueryWrapper<Section> sectionWrapper = new LambdaQueryWrapper<>();
        sectionWrapper.eq(Section::getVideoSourceId, videoId);
        Section section = sectionMapper.selectOne(sectionWrapper);

        LambdaQueryWrapper<Course> courseWrapper = new LambdaQueryWrapper<>();
        courseWrapper.eq(Course::getId, section.getCourseId());
        Course course = super.getOne(courseWrapper);

        LambdaQueryWrapper<Teacher> teacherWrapper = new LambdaQueryWrapper<>();
        teacherWrapper.eq(Teacher::getId, course.getTeacherId());
        Teacher teacher = teacherMapper.selectOne(teacherWrapper);

        sectionWrapper.clear();
        sectionWrapper.eq(Section::getCourseId, course.getId());
        List<Section> sectionList = sectionMapper.selectList(sectionWrapper);

        videoPlayPageVo.setCourseTitle(course.getTitle());
        videoPlayPageVo.setCourseViewCount(course.getViewCount());
        videoPlayPageVo.setCourseModifyTime(course.getGmtModified());
        videoPlayPageVo.setTeacherAvatar(teacher.getAvatar());
        videoPlayPageVo.setTeacherName(teacher.getName());
        videoPlayPageVo.setTeacherCareer(teacher.getCareer());
        videoPlayPageVo.setSectionCount((long) sectionList.size());

        List<SectionVo> sectionVoList = sectionList.stream().map(sec -> new SectionVo(sec.getId(), sec.getTitle(), sec.getVideoSourceId())).collect(Collectors.toList());

        videoPlayPageVo.setSectionVoList(sectionVoList);
        return videoPlayPageVo;
    }

    @Override
    public Integer courseInsertCount(String date) {
        Integer count = courseMapper.courseInsertCount(date);
        return count;
    }


}
